/*
#
#  Copyright 2011 Matthew Jannace
#
#  This file is part of RoboCode BlackHoleAgent
#
#  RoboCode BlackHoleAgent is free software: you can redistribute it and/or
#  modify it under the terms of the GNU General Public License as
#  published by the Free Software Foundation, either version 3 of the
#  License, or (at your option) any later version.
#
#  RoboCode BlackHoleAgent is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
#  General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with RoboCode BlackHoleAgent. If not, see
#  <http://www.gnu.org/licenses/>.
#
 */
package com.jannaceltd.TeamBlackHoleBeer.Modules.Targeting.TargetingMethods;

import com.jannaceltd.TeamBlackHoleBeer.Utilities.MathUtils;
import java.awt.geom.*;
import robocode.util.Utils;

/**
 *
 * @author Matthew Jannace <mjannace@gmail.com>
 * @version 1.0
 * 
 * Based on the GuessFactor Targeting Tutorial
 * @link http://robowiki.net/wiki/GuessFactor_Targeting_Tutorial
 */
public class WaveBullet {

    private Point2D.Double pos;
    private double relativeBearing, absoluteBearing, power;
    private long fireTime;
    private int direction;
    private int[] returnSegment;

    /**
     * Gets the Direction
     * @return
     */
    public int getDirection() {
        return direction;
    }

    /**
     * Sets the DirectionF
     * @param direction
     */
    public void setDirection(int direction) {
        this.direction = direction;
    }

    /**
     * Gets the Fire time of the Shot
     * @return
     */
    public long getFireTime() {
        return fireTime;
    }

    /**
     * Sets the Fire Time of the Shot
     * @param fireTime
     */
    public void setFireTime(long fireTime) {
        this.fireTime = fireTime;
    }

    /**
     * Gets the Fire Power of the Shot
     * @return
     */
    public double getPower() {
        return power;
    }

    /**
     * Sets the Fire Power of the shot
     * @param power
     */
    public void setPower(double power) {
        this.power = power;
    }

    /**
     * Gets the Return Segment
     * @return returnSegment
     */
    public int[] getReturnSegment() {
        return returnSegment;
    }

    /**
     * Sets the Return Segment
     * @param returnSegment
     */
    public void setReturnSegment(int[] returnSegment) {
        this.returnSegment = returnSegment;
    }

    /**
     * Gets the Absolute Bearing
     * @return absoluteBearing
     */
    public double getAbsoluteBearing() {
        return absoluteBearing;
    }

    /**
     * Gets the Relative Bearing
     * @return relativeBearing
     */
    public double getRelativeBearing() {
        return relativeBearing;
    }

    /**
     * Gets the Star position
     * @return
     */
    public Point2D.Double getPos() {
        return pos;
    }

    /**
     * Gets the Start X of where the bullet is fired
     * @return X location
     */
    public double getStartX() {
        return pos.getX();
    }

    /**
     * Sets the Start X of where the bullet is fired
     * @param startX
     */
    public void setStartX(double startX) {
        this.pos.setLocation(startX, this.pos.getY());
    }

    /**
     * Gets the Start Y of where the bullet is fired
     * @return Y location
     */
    public double getStartY() {
        return pos.getY();
    }

    /**
     * Sets the Start Y of where the bullet is fired
     * @param startY
     */
    public void setStartY(double startY) {
        this.pos.setLocation(this.pos.getX(), startY);
    }

    /**
     * Creates a new WaveBullet Object
     * @param x
     * @param y
     * @param absoluteBearing
     * @param relativeBearing
     * @param power
     * @param direction
     * @param time
     * @param segment
     */
    public WaveBullet(double x, double y, double absoluteBearing, double relativeBearing, double power,
            int direction, long time, int[] segment) {

        pos = new Point2D.Double(x, y);
        this.absoluteBearing = absoluteBearing;
        this.relativeBearing = relativeBearing;
        this.power = power;
        this.direction = direction;
        fireTime = time;
        returnSegment = segment;
    }

    /**
     * Gets the Bullets Speed
     * @return Bullet Speed
     */
    public double getBulletSpeed() {
        return 20 - power * 3;
    }

    /**
     * The Maximum Angle the enemy could move from when the bullet is fired to
     * when it should intercept the enemy
     * @return
     */
    public double maxEscapeAngle() {
        return Math.asin(8 / getBulletSpeed());
    }

    /**
     * Checks if the distance from the wave origin to our enemy has passed
     * the distance the bullet would have traveled
     * @param enemyX
     * @param enemyY
     * @param currentTime
     * @return True is the wave passed the Enemy else False the bullet is still in flight
     */
    public boolean checkHit(double enemyX, double enemyY, long currentTime) {
        // if the distance from the wave origin to our enemy has passed
        // the distance the bullet would have traveled...
        if (pos.distance(enemyX, enemyY) <= (currentTime - fireTime) * getBulletSpeed()) {
            double desiredDirection = MathUtils.calcAngle(new Point2D.Double(enemyX, enemyY), pos);
            double angleOffset = Utils.normalRelativeAngle(desiredDirection - absoluteBearing);
            double guessFactor = Math.max(-1, Math.min(1, angleOffset / maxEscapeAngle())) * direction;
            int index = (int) Math.round((returnSegment.length - 1) / 2 * (guessFactor + 1));
            returnSegment[index]++;
            return true;
        }
        return false;
    }
}
